/*
 * Copyright (c) 2018 - 2028. www.vtuzx.com Inc. All Rights Reserved
 */
package com.vtuzx.kingdee.xqc_api.service.impl;

import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import com.vtuzx.core.VtuzxException;
import com.vtuzx.core.bean.dto.VtuzxMap;
import com.vtuzx.core.bean.dto.VtuzxPage;
import com.vtuzx.core.bean.dto.VtuzxToken;
import com.vtuzx.core.constant.IVtuzxConst;
import com.vtuzx.core.file.excel.VtuzxExcel;
import com.vtuzx.core.file.excel.VtuzxExcelCell;
import com.vtuzx.core.file.excel.VtuzxExcelRow;
import com.vtuzx.core.file.excel.VtuzxExcelSheet;
import com.vtuzx.core.utils.VtuzxUtil;
import com.vtuzx.fast.utils.FastUtil;
import com.vtuzx.kingdee.xqc_api.service.IXqcConfigService;
import com.vtuzx.kingdee.xqc_api.service.IXqcInventoryService;
import com.vtuzx.kingdee.xqc_api.service.IXqcPurchaseService;
import com.vtuzx.kingdee.xqc_api.service.IXqcSyncKingdeeOrderService;
import com.vtuzx.kingdee.xqc_core.bean.VtuzxArrayList;
import com.vtuzx.kingdee.xqc_core.bean.xqc.BillMaterial;
import com.vtuzx.kingdee.xqc_core.bean.xqc.BillMaterialBox;
import com.vtuzx.kingdee.xqc_core.constant.BillEvent;
import com.vtuzx.kingdee.xqc_core.constant.BillStatus;
import com.vtuzx.kingdee.xqc_core.constant.BillType;
import com.vtuzx.kingdee.xqc_core.constant.IXqcConst;
import com.vtuzx.kingdee.xqc_core.dao.*;
import com.vtuzx.kingdee.xqc_core.service.IJiKeYunApiService;
import com.vtuzx.web.bean.VtuzxDownloadBean;
import com.vtuzx.web.dao.mongo.CustomerDao;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import javax.print.Doc;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 采购服务
 */
@Service
public class XqcPurchaseServiceImpl implements IXqcPurchaseService {

    /** Logger */
    private static final Logger _logger = LoggerFactory.getLogger(XqcPurchaseServiceImpl.class);

    @Autowired
    private IXqcConfigService configService;

    @Autowired
    private PurReturnDao purReturnDao;

    @Autowired
    private PurReturnDetailDao purReturnDetailDao;

    @Autowired
    private IXqcInventoryService inventoryService;

    @Autowired
    private CustomerDao customerDao;

    @Autowired
    private XqcProduceServiceImpl produceService;

    @Autowired
    private PurColDao purColDao;

    @Autowired
    private TestRoomDao testRoomDao;

    @Autowired
    private MaterialDao materialDao;

    @Autowired
    private SupplierDao supplierDao;

    @Autowired
    private PurColDetailDao purColDetailDao;

    @Autowired
    private PurInDao purInDao;

    @Autowired
    private PurInDetailDao purInDetailDao;

    @Autowired
    private StockDao stockDao;

    @Autowired
    private PurInDetailBoxDao purInDetailBoxDao;

    @Autowired
    private IXqcSyncKingdeeOrderService syncKingdeeOrderService;

    /** 金蝶 */
    @Autowired
    private PurOrderDetailDao purOrderDetailDao;

    @Autowired
    private StoreTokenDao storeTokenDao;

    @Autowired
    private IJiKeYunApiService iJiKeYunApiService;

    @Autowired
    private InventoryDetailDao inventoryDetailDao;

    @Autowired
    private InventoryDao inventoryDao;

    @Autowired
    private PrdColDetailDao prdColDetailDao;

    @Override
    public void bindPurColBoxRfid(String boxNo, String rfid) throws VtuzxException {
        Document boxDoc = purColDetailDao.findOne(Criteria.where("boxNo").is(boxNo).and("inStock").ne(true));
        if (boxDoc == null) {
            throw new VtuzxException(IXqcConst.Msg_E_XQC_box_not_exist, boxNo);
        }
        String billNo = VtuzxUtil.getString(boxDoc, "billNo");
        Document purColDoc = purColDao.findOne(Criteria.where("billNo").is(billNo));
        if (purColDoc == null) {
            throw new VtuzxException(IXqcConst.Msg_E_XQC_box_not_exist, boxNo);
        }
        String status = VtuzxUtil.getString(purColDoc, "status");
        if (!BillStatus.Audit.hit(status)) {
            throw new VtuzxException(IXqcConst.Msg_E_XQC_box_not_audit, boxNo);
        }
        Criteria lastPurColBindRfid = Criteria.where("rfid").is(rfid).and("inStock").ne(true);
        Document lastPurColDetail = purColDetailDao.findOne(lastPurColBindRfid);
        if(lastPurColDetail != null) {
            purColDetailDao.updateByIdRedirect(lastPurColDetail.getObjectId(IVtuzxConst.Key__id), new Document("$unset", new Document("rfid", 1)));
            purColDao.updateOneRedirect(Criteria.where("billNo").is(VtuzxUtil.getString(lastPurColDetail, "billNo")), new Document("$inc", new Document("bindBoxCount", -1)));
        }
        purColDetailDao.updateById(boxDoc.getObjectId(IVtuzxConst.Key__id), new Document("rfid", rfid));
        if (VtuzxUtil.isEmpty(VtuzxUtil.getString(boxDoc, "rfid"))) {
            purColDao.updateByIdRedirect(purColDoc.getObjectId(IVtuzxConst.Key__id), new Document("$inc", new Document("bindBoxCount", 1)));
        }
    }


    /**
     * 上传采购收货单
     */
    @Override
    public void uploadPurColBill(ObjectId _userId, String userName, File file) throws Exception {
//        uploadBoxNo(file);
        List<VtuzxExcelSheet> sheets = VtuzxExcel.read(file);
        VtuzxExcelSheet sheet = sheets.get(0);
        int rowSize = sheet.rowSize();
        List<Map<String, Object>> newBillList = new ArrayList<>();
        String preMaterialNo = "";
        String preBatchNo = "";
        Map<String, Object> bill = null;
        for (int i = 1; i < rowSize; i++) {
            String materialNo = "";
            String materialName = "";
            String materialSpec = "";
            String batchNo = "";
            double purCount = 0;
            String boxNo = "";
            double count = 0;
            String comment = "";
            int cellSize = sheet.row(i).cellSize();
            for(int ci = 0; ci < cellSize; ci++) {
                if (sheet.row(i).cell(ci).col() == 0) materialNo = sheet.row(i).cell(ci).strCellValue();
                if (sheet.row(i).cell(ci).col() == 1) materialName = sheet.row(i).cell(ci).strCellValue();
                if (sheet.row(i).cell(ci).col() == 2) materialSpec = sheet.row(i).cell(ci).strCellValue();
                if (sheet.row(i).cell(ci).col() == 3) batchNo = sheet.row(i).cell(ci).strCellValue().replaceAll("\\.0", "");
                if (sheet.row(i).cell(ci).col() == 4) purCount = sheet.row(i).cell(ci).doubleCellValue();
                if (sheet.row(i).cell(ci).col() == 5) boxNo = sheet.row(i).cell(ci).strCellValue();
                if (sheet.row(i).cell(ci).col() == 6) count = sheet.row(i).cell(ci).doubleCellValue();
                if (sheet.row(i).cell(ci).col() == 7) comment = sheet.row(i).cell(ci).strCellValue();
            }

            if (!materialNo.equals(preMaterialNo) || !batchNo.equals(preBatchNo)) {
                bill = new HashMap<>();
                newBillList.add(bill);
                bill.put("materialNo", materialNo);
                bill.put("materialName", materialName);
                bill.put("materialSpec", materialSpec);
//                bill.put("supplierNo", "");
//                bill.put("supplierName", "");
                bill.put("batchNo", batchNo);
                bill.put("purCount", purCount);
//                bill.put("produceDate", "");
//                bill.put("exp", "");
                List<Map<String, Object>> boxList = new ArrayList<>();
                bill.put("boxList", boxList);
            }
            List<Map<String, Object>> boxList = VtuzxUtil.getObject(bill, "boxList");
            boxList.add(new VtuzxMap("boxNo", boxNo).append("count", count).append("comment", comment));
            preMaterialNo = materialNo;
            preBatchNo = batchNo;
        }
        for(Map<String, Object> newBill: newBillList) {
            VtuzxMap res = savePurColBill(_userId, userName, newBill);
            String billNo = VtuzxUtil.getString(res, "billNo");
            auditPurColBill(_userId, userName, billNo);
        }
    }

    @Override
    public VtuzxMap savePurColBill(ObjectId _userId, Map<String, Object> param) throws VtuzxException {
        // 获取用户信息
        Document user = customerDao.findById(_userId);
        return savePurColBill(_userId, VtuzxUtil.getString(user, "name"), param);
    }

    @Override
    public VtuzxMap savePurColBill(ObjectId _userId, String userName, Map<String, Object> param) throws VtuzxException {
        // 获取用户信息
        String billNo = VtuzxUtil.getString(param, "billNo");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
        String unit = "kg";
        String goodsType = "";
        if (!VtuzxUtil.isEmpty(materialDoc)) {
            unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
            goodsType = VtuzxUtil.getString(materialDoc, "goodsType");
        }
        Document doc = new Document();
        doc.append("materialNo", materialNo);
        doc.append("materialName", VtuzxUtil.getString(param, "materialName"));
        doc.append("materialSpec", VtuzxUtil.getString(param, "materialSpec"));
        doc.append("supplierNo", VtuzxUtil.getString(param, "supplierNo"));
        doc.append("supplierName", VtuzxUtil.getString(param, "supplierName"));
        doc.append("batchNo", VtuzxUtil.getString(param, "batchNo"));
        doc.append("produceDate", VtuzxUtil.getString(param, "produceDate"));
        doc.append("exp", VtuzxUtil.getInt(param, "exp"));
        doc.append("purCount", VtuzxUtil.getDouble(param, "purCount"));
        doc.append("remark", VtuzxUtil.getString(param, "remark"));
        // 计算总箱数和总称重
        List<Map<String, Object>> boxList = VtuzxUtil.getObject(param, "boxList");
        double total = 0;
        for(Map<String, Object> box: boxList) {
            double count = VtuzxUtil.getDouble(box, "count");
            total += count;
        }
        doc.append("count", total);
        doc.append("unit", unit);
        doc.append("boxCount", boxList.size());

        List<Document> detailList = new ArrayList<>();
        if (VtuzxUtil.isEmpty(billNo)) {
            billNo = IXqcConst.createBillNo(BillType.CGSH);
            _logger.info(String.format("新建单据号：%s", billNo));
            doc.append("billNo", billNo);
            doc.append("status", BillStatus.Save.toString());
            doc.append("_createUserId", _userId);
            doc.append("createUserName", userName);
            purColDao.insertOne(doc);
            doc.append("colType", "purCol").append("goodsType", goodsType);
            doc.remove("_id");
            doc.remove("createTime");
            doc.remove("updateTime");
            doc.append("colUserName", userName);
            doc.append("colTime", VtuzxUtil.formatYmdHmsF(new Date()));
            testRoomDao.insertOne(doc);
        } else {
            doc.append("_updateUserId", _userId);
            doc.append("updateUserName", userName);
            UpdateResult res = purColDao.updateOne(Criteria.where("billNo").is(billNo).and("status").is(BillStatus.Save.toString()), doc);
            if (res.getModifiedCount() == 0) {
                throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
            }
            Iterator<Document> detailItr = purColDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
            while(detailItr.hasNext()) {
                detailList.add(detailItr.next());
            }
        }
        List<ObjectId> _delIds = new ArrayList<>();
        List<Document> insertList = new ArrayList<>();
        for(Map<String, Object> box: boxList) {
            String boxNo = VtuzxUtil.getString(box, "boxNo");
            String comment = VtuzxUtil.getString(box, "comment");
            boolean exist = false;
            for(Document detail: detailList) {
                String boxNoDB = VtuzxUtil.getString(detail, "boxNo");
                if (boxNo.equals(boxNoDB)) {
                    purColDetailDao.updateById(
                            detail.getObjectId(IVtuzxConst.Key__id),
                            new Document("count", VtuzxUtil.getDouble(box, "count"))
                                    .append("_updateUserId", _userId)
                                    .append("updateUserName", userName)
                                    .append("comment", comment)
                    );
                    exist = true;
                    detailList.remove(detail);
                    break;
                }
            }
            if (!exist) {
                insertList.add(new Document("count", VtuzxUtil.getDouble(box, "count"))
                        .append("unit", unit)
                        .append("billNo", billNo)
                        .append("boxNo", VtuzxUtil.getString(box, "boxNo"))
                        .append("comment", VtuzxUtil.getString(box, "comment"))
                        .append("inStock", false)
                        .append("_insertUserId", _userId)
                        .append("insertUserName", userName));
            }
        }
        for(Document detail: detailList) {
            _delIds.add(VtuzxUtil.getObject(detail, IVtuzxConst.Key__id));
        }
        _logger.info(String.format("删除单据分录行：%d", _delIds.size()));
        if (_delIds.size() > 0) {
            purColDetailDao.deleteMany(Criteria.where(IVtuzxConst.Key__id).in(_delIds));
        }
        _logger.info(String.format("新建单据分录行：%d", insertList.size()));
        if (insertList.size() > 0) {
            purColDetailDao.insertMany(insertList);
        }
        return new VtuzxMap("billNo", billNo);
    }

    @Override
    public void deletePurColBill(ObjectId _userId, String billNo) throws VtuzxException {
        DeleteResult res = purColDao.deleteOne(Criteria.where("billNo").is(billNo).and("status").is(BillStatus.Save.toString()));
        if (res.getDeletedCount() == 0) {
            throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
        }
        purColDetailDao.deleteMany(Criteria.where("perColBillNo").is(billNo));
    }

    @Override
    public VtuzxMap auditPurColBill(ObjectId _userId, String billNo) throws VtuzxException {
        // 获取用户信息
        Document user = customerDao.findById(_userId);
        return auditPurColBill(_userId, VtuzxUtil.getString(user, "name"), billNo);
    }

    @Override
    public VtuzxMap auditPurColBill(ObjectId _userId, String userName, String billNo) throws VtuzxException {
        Criteria cond = Criteria.where("billNo").is(billNo).and("status").is(BillStatus.Save.toString());
        Document updateDoc = new Document("status", BillStatus.Audit.toString());
        updateDoc.append("_auditUserId", _userId);
        updateDoc.append("auditUserName", userName);
        updateDoc.append("auditTime", new Date());
        UpdateResult res = purColDao.updateOne(cond, updateDoc);
        if (res.getModifiedCount() == 0) {
            throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
        }
        return new VtuzxMap("status", BillStatus.Audit.toString());
    }

    @Override
    public VtuzxMap unauditPurColBill(ObjectId _userId, String billNo) throws VtuzxException {
        Iterator<Document> purColDetailItr = purColDetailDao.findList(Criteria.where("perColBillNo").is(billNo).and("_insertUserId").is(_userId), null, 0, 0);
        while (purColDetailItr.hasNext()) {
            Document purColDetailDoc = purColDetailItr.next();
            boolean inStock = VtuzxUtil.getBoolean(purColDetailDoc, "inStock");
            if (inStock) {
                throw new VtuzxException("订单存在已入库的分录,不能进行反审操作");
            }
        }
        Criteria cond = Criteria.where("billNo").is(billNo).and("status").is(BillStatus.Audit.toString());
        Document updateDoc = new Document("$set", new Document("status", BillStatus.Save.toString()));
        updateDoc.append("$unset", new Document("_auditUserId", 1).append("auditUserName", 1).append("auditTime", 1));
        UpdateResult res = purColDao.updateOneRedirect(cond, updateDoc);
        if (res.getModifiedCount() == 0) {
            throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
        }
        return new VtuzxMap("status", BillStatus.Save.toString());
    }

    @Override
    public VtuzxMap getPurColMaterialByRfid(List<String> rfidList) {
        Iterator<Document> boxItr = purColDetailDao.findList(Criteria.where("rfid").in(rfidList).and("inStock").ne(true), null, 0, 0);
        List<Document> boxList = new ArrayList<>();
        List<String> billNoList = new ArrayList<>();
        while(boxItr.hasNext()) {
            Document box = boxItr.next();
            String billNo = VtuzxUtil.getString(box, "billNo");
            boxList.add(box);
            if (!billNoList.contains(billNo)) {
                billNoList.add(billNo);
            }
        }
        if (VtuzxUtil.isEmpty(boxList)) {
            return new VtuzxMap(IVtuzxConst.Key_data, new ArrayList<>());
        }
        Iterator<Document> billItr = purColDao.findList(Criteria.where("billNo").in(billNoList).and("status").is(BillStatus.Audit.toString()), null, 0, 0);
        VtuzxMap billMap = FastUtil.itr2Map(billItr, "billNo");
        for(int i = boxList.size() - 1; i >= 0; i--) {
            Document box = boxList.get(i);
            String billNo = VtuzxUtil.getString(box, "billNo");
            Document bill = VtuzxUtil.getObject(billMap, billNo);
            if (bill == null) {
                boxList.remove(i);
                continue;
            }
            if (bill.containsKey("count")) {
                bill.append("countTotal", VtuzxUtil.removeObject(bill, "count"));
            }
            box.putAll(bill);
            box.remove(IVtuzxConst.Key__id);
            box.remove(IVtuzxConst.Key_createTime);
            box.remove(IVtuzxConst.Key_updateTime);
            box.remove("auditTime");
            box.remove("_createUserId");
            box.remove("_updateUserId");
            box.remove("createUserName");
            box.remove("updateUserName");
            box.remove("auditUserName");
        }
        return new VtuzxMap(IVtuzxConst.Key_data, boxList);
    }

    @Override
    public VtuzxMap getPurColMaterial(String boxNoKey) throws VtuzxException {
        String boxNo;
        if (boxNoKey.contains("|;")) {
            String[] boxValues = boxNoKey.split("\\|\\;");
            if (boxValues.length == 5) {
                String supplierNo = boxValues[0];
                String materialNo = boxValues[1];
                String batchNo = boxValues[2];
                String flowNo = boxValues[3];
                int count = Integer.parseInt(boxValues[4]);
                return getPurColMaterial(boxNoKey, supplierNo, materialNo, batchNo, flowNo, count);
            }
            boxNo = boxValues[boxValues.length - 1];
        } else {
            boxNo = boxNoKey;
        }
        Document box = purColDetailDao.findOne(Criteria.where("boxNo").is(boxNo));
        if (box == null) {
            throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
        }
        boolean inStock = VtuzxUtil.getBoolean(box, "inStock");
        if (inStock) {
            throw new VtuzxException(IXqcConst.Msg_E_XQC_in_stock, boxNo);
        }
        String billNo = VtuzxUtil.getString(box, "billNo");
        Document bill = purColDao.findOne(Criteria.where("billNo").is(billNo));
        if (bill == null) {
            throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
        }
        bill.append("countTotal", VtuzxUtil.removeObject(bill, "count"));
        if (!BillStatus.Audit.hit(VtuzxUtil.getString(bill, "status"))) {
            throw new VtuzxException(String.format("箱号的采购收货单[%s]未审核!", billNo));
        }
        VtuzxMap res = new VtuzxMap(box);
        res.putAll(bill);
        res.remove(IVtuzxConst.Key__id);
        res.remove(IVtuzxConst.Key_createTime);
        res.remove(IVtuzxConst.Key_updateTime);
        res.remove("auditTime");
        res.remove("_createUserId");
        res.remove("_updateUserId");
        res.remove("createUserName");
        res.remove("updateUserName");
        res.remove("auditUserName");
        return res;
    }

    public VtuzxMap getPurColMaterial(String boxNo, String supplierNo, String materialNo, String batchNo, String flowNo, int count) throws VtuzxException {
        VtuzxMap res = new VtuzxMap();
        Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
        if (materialDoc == null) {
            throw new VtuzxException("物料不存在");
        }
        Document supplierDoc = supplierDao.findOne(Criteria.where("fNumber").is(supplierNo));
        if (supplierDoc == null) {
            throw new VtuzxException("供应商不存在");
        }
        res.append("materialNo", materialNo);
        res.append("materialName", VtuzxUtil.getString(materialDoc, "fName"));
        res.append("materialSpec", VtuzxUtil.getString(materialDoc, "fSpecification"));
        res.append("unit", VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber"));
        res.append("supplierNo", supplierNo);
        res.append("supplierName", VtuzxUtil.getString(supplierDoc, "fName"));
        res.append("batchNo", batchNo);
        res.append("count", count);
        res.append("boxCount", 1);
        res.append("billNo", "");
        res.append("boxNo", boxNo);
        res.append("inStock", false);
        res.append("rfid", "");
        res.append("barcodeType", "BC");
//        "supplierName": "",
//        "res": true,
//        "batchNo": "20220602134141",
//        "materialSpec": "混等",
//        "count": 5.0,
//        "supplierNo": "",
//        "materialName": "鲜海参 滚子",
//        "unit": "jin",
        return res;
    }

    @Override
    public VtuzxMap getPurColMaterialForBind(String boxNo) throws VtuzxException {
        Document boxDoc = purColDetailDao.findOne(Criteria.where("boxNo").is(boxNo));
        if (boxDoc == null) {
            throw new VtuzxException(IXqcConst.Msg_E_XQC_box_not_exist, boxNo);
        }
        boolean inStock = VtuzxUtil.getBoolean(boxDoc, "inStock");
        if (inStock) {
//            throw new VtuzxException(IXqcConst.Msg_E_XQC_in_stock, boxNo);
        }
        String billNo = VtuzxUtil.getString(boxDoc, "billNo");
        Document purColDoc = purColDao.findOne(Criteria.where("billNo").is(billNo));
        if (purColDoc == null) {
            throw new VtuzxException(IXqcConst.Msg_E_XQC_box_not_exist, boxNo);
        }
        String status = VtuzxUtil.getString(purColDoc, "status");
        if (!BillStatus.Audit.hit(status)) {
            throw new VtuzxException(IXqcConst.Msg_E_XQC_box_not_audit, boxNo);
        }
        return new VtuzxMap("materialNo", VtuzxUtil.getString(purColDoc, "materialNo"))
                .append("materialName", VtuzxUtil.getString(purColDoc, "materialName"))
                .append("materialSpec", VtuzxUtil.getString(purColDoc, "materialSpec"))
                .append("batchNo", VtuzxUtil.getString(purColDoc, "batchNo"))
                .append("unit", VtuzxUtil.getString(purColDoc, "unit"))
                .append("count", VtuzxUtil.getDouble(boxDoc, "count"))
                .append("supplierName", VtuzxUtil.getString(purColDoc, "supplierName"))
                .append("instockDate", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(purColDoc, "createTime")))
                .append("produceDate", VtuzxUtil.getString(purColDoc, "produceDate"))
                .append("exp", VtuzxUtil.getInt(purColDoc, "exp"));
    }

    @Override
    public VtuzxMap getPurColBill(ObjectId _userId, Map<String, Object> param, int pageIndex, int pageSize) {
        boolean isNoStockIn = VtuzxUtil.getBoolean(param, "isNoStockIn");
        String status = VtuzxUtil.getString(param, "status");
        String billNo = VtuzxUtil.getString(param, "billNo");
        boolean checkNoRfid = !VtuzxUtil.isEmpty(VtuzxUtil.getString(param, "isNoRfid"));
        boolean isNoRfid = VtuzxUtil.getBoolean(param, "isNoRfid");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String materialName = VtuzxUtil.getString(param, "materialName");
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        List<String> auditTime = VtuzxUtil.getObject(param, "auditTime");

        Criteria cond = new Criteria();
//        if (checkNoRfid) {
//            cond.getCriteriaObject().append("$where", "this.boxCount " + (isNoRfid? "!=": "=") + " this.bindBoxCount");
//            cond.and("$where").is("this.boxCount " + (isNoRfid? "!=": "=") + " this.bindBoxCount");
//        }
        if (!VtuzxUtil.isEmpty(status)) {
            cond.and("status").is(status);
        }
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(materialNo)) {
            cond.and("materialNo").regex(materialNo);
        }
        if (!VtuzxUtil.isEmpty(materialName)) {
            cond.and("materialName").regex("^.*" + materialName + ".*$");
        }
        if (!VtuzxUtil.isEmpty(batchNo)) {
            cond.and("batchNo").is(batchNo);
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        if (!VtuzxUtil.isEmpty(auditTime)) {
            cond.and("auditTime").gte(VtuzxUtil.parseDate(auditTime.get(0))).lte(VtuzxUtil.parseDate(auditTime.get(1) + " 23:59:59"));
        }
        if (!VtuzxUtil.isEmpty(VtuzxUtil.getString(param, "isNoStockIn"))) {
            Iterator<Document> colDetailItr = purColDetailDao.findList(Criteria.where("inStock").ne(true), null, 0, 0);
            List<String> notInStockBillNoList = new ArrayList<>();
            while(colDetailItr.hasNext()) {
                Document colDetail = colDetailItr.next();
                String notInStockBillNo = VtuzxUtil.getString(colDetail, "billNo");
                if (!notInStockBillNoList.contains(notInStockBillNo)) {
                    notInStockBillNoList.add(notInStockBillNo);
                }
            }
            if (isNoStockIn) {
                cond.and("billNo").nin(notInStockBillNoList);
            } else {
                cond.and("billNo").in(notInStockBillNoList);
            }
        }
//        VtuzxPage page = purColDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        VtuzxPage page = purColDao.getPageList(cond.getCriteriaObject(), checkNoRfid, isNoRfid, pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(itr -> {
            VtuzxMap data = new VtuzxMap(itr);
            int exp = VtuzxUtil.getInt(data, "exp");
            int boxCount = VtuzxUtil.getInt(data, "boxCount");
            int bindBoxCount = VtuzxUtil.getInt(data, "bindBoxCount");
            Date date = VtuzxUtil.parseDate(VtuzxUtil.getObject(data, "produceDate"));
            String expDate;
            if (exp <= 0) {
                expDate = "";
            } else {
                expDate = VtuzxUtil.formatYmdF(VtuzxUtil.calcDate(date, Calendar.DAY_OF_MONTH, exp));
            }
            data.append("isNotRfid", boxCount - bindBoxCount);
            data.append("expDate", expDate);
            data.append("id", VtuzxUtil.removeString(data, IVtuzxConst.Key__id));
            data.append(IVtuzxConst.Key_createTime, VtuzxUtil.formatYmdHmF(VtuzxUtil.removeObject(data, IVtuzxConst.Key_createTime)));
            data.remove(IVtuzxConst.Key_updateTime);
            data.append("auditTime", VtuzxUtil.formatYmdHmF(VtuzxUtil.removeObject(data, "auditTime")));
            data.remove("_createUserId");
            data.remove("_updateUserId");
            data.remove("_auditUserId");
            return data;
        });
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPurColBillDetail(ObjectId _userId, String billNo) throws VtuzxException {
        Document doc = purColDao.findOne(Criteria.where("billNo").is(billNo));
        if (doc == null) {
            throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
        }
        VtuzxMap header = new VtuzxMap(doc);
//        header.append("billNo", VtuzxUtil.getObject(doc, "billNo"));
//        header.append("status", VtuzxUtil.getObject(doc, "status"));
//        header.append("materialNo", VtuzxUtil.getObject(doc, "materialNo"));
//        header.append("materialName", VtuzxUtil.getObject(doc, "materialName"));
//        header.append("materialSpec", VtuzxUtil.getObject(doc, "materialSpec"));
//        header.append("supplierNo", VtuzxUtil.getObject(doc, "supplierNo"));
//        header.append("supplierName", VtuzxUtil.getObject(doc, "supplierName"));
//        header.append("batchNo", VtuzxUtil.getObject(doc, "batchNo"));
//        header.append("produceDate", VtuzxUtil.getObject(doc, "produceDate"));
//        header.append("exp", VtuzxUtil.getObject(doc, "exp"));
//        header.append("purCount", VtuzxUtil.getObject(doc, "purCount"));
        String materialNo = VtuzxUtil.getString(header, "materialNo");
        Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
        String unitName = VtuzxUtil.getString(materialDoc, "fBaseUnitIdFName");
        header.append(IVtuzxConst.Key_createTime, VtuzxUtil.formatYmdHmF(VtuzxUtil.removeObject(header, IVtuzxConst.Key_createTime)));
        Iterator<Document> boxItr = purColDetailDao.findList(Criteria.where("billNo").is(billNo), new Document("boxNo", 1), 0, 0);
        List<VtuzxMap> boxList = new ArrayList<>();
        while(boxItr.hasNext()) {
            Document boxDoc = boxItr.next();
            VtuzxMap purColDetailMap = new VtuzxMap(boxDoc);
            purColDetailMap.remove(IVtuzxConst.Key_createTime);
            purColDetailMap.remove(IVtuzxConst.Key_updateTime);
            purColDetailMap.remove("_createUserId");
            purColDetailMap.remove("createUserName");
            purColDetailMap.remove("_updateUserId");
            purColDetailMap.remove("updateUserName");
            purColDetailMap.append("id", VtuzxUtil.removeString(purColDetailMap, IVtuzxConst.Key__id));
            purColDetailMap.append("unitName", unitName);
            boxList.add(purColDetailMap);
        }
        return new VtuzxMap("header", header).append("boxList", boxList);
    }

    @Override
    public VtuzxDownloadBean downloadPurColBillBarcodeList(ObjectId _userId, List<String> billNoList) throws Exception {
        List<VtuzxMap> detailList = new ArrayList<>();
        for(String billNo: billNoList) {
            VtuzxMap detail = getPurColBillDetail(_userId, billNo);
            detailList.add(detail);
        }
        return configService.downloadBillBarcode(BillType.CGSH, detailList);
    }

    @Override
    public VtuzxDownloadBean downloadPurColBillBarcode(ObjectId _userId, String billNo) throws Exception {
        VtuzxMap detail = getPurColBillDetail(_userId, billNo);
//        VtuzxMap header = VtuzxUtil.getObject(detail, "header");
//        List<VtuzxMap> boxList = VtuzxUtil.getObject(detail, "boxList");
        List<VtuzxMap> detailList = new ArrayList<>();
        detailList.add(detail);
        return configService.downloadBillBarcode(BillType.CGSH, detailList);
    }

    @Override
    public void saveUserPurInByPurColList(ObjectId _userId, String userName, String stockNo, String locationNo, List<String> billNoList, String source, boolean isBc) throws Exception {
        List<ObjectId> _detailIdList = new ArrayList<>();
        Iterator<Document> purColItr = purColDao.findList(Criteria.where("billNo").in(billNoList), null, 0, 0);
        VtuzxMap purColMap = new VtuzxMap();
        while(purColItr.hasNext()) {
            Document purColDoc = purColItr.next();
            purColDoc.append("countTotal", VtuzxUtil.removeObject(purColDoc, "count"));
            if (BillStatus.Audit.hit(VtuzxUtil.getString(purColDoc, "status"))) {
                String purColBillNo = VtuzxUtil.getString(purColDoc, "billNo");
                purColMap.append(purColBillNo, purColDoc);
            }
        }
        Criteria cond = new Criteria("billNo").in(billNoList);
        if (isBc) {
            cond.and("isBc").is(true);
        }
        Iterator<Document> purColBoxItr = purColDetailDao.findList(cond, null, 0, 0);
        while(purColBoxItr.hasNext()) {
            Document purColBoxDoc = purColBoxItr.next();
            boolean inStock = VtuzxUtil.getBoolean(purColBoxDoc, "inStock");
            if (inStock) {
                continue;
            }
            String purColBoxBillNo = VtuzxUtil.getString(purColBoxDoc, "billNo");
            Document purColDoc = VtuzxUtil.getObject(purColMap, purColBoxBillNo);
            if (purColDoc == null) {
                continue;
            }
            VtuzxMap detailBoxMap = new VtuzxMap(purColBoxDoc);
            detailBoxMap.putAll(purColDoc);
            detailBoxMap.remove(IVtuzxConst.Key__id);
            detailBoxMap.remove(IVtuzxConst.Key_createTime);
            detailBoxMap.remove(IVtuzxConst.Key_updateTime);
            detailBoxMap.remove("auditTime");
            detailBoxMap.remove("_createUserId");
            detailBoxMap.remove("_updateUserId");
            detailBoxMap.remove("createUserName");
            detailBoxMap.remove("updateUserName");
            detailBoxMap.remove("auditUserName");
            String boxNo = VtuzxUtil.getString(detailBoxMap, "boxNo");
            double count = VtuzxUtil.getDouble(detailBoxMap, "count");
            ObjectId _detailId = addUserPurInMaterialBoxInner(detailBoxMap, _userId, userName, stockNo, locationNo, boxNo, count, false, "", "");
            FastUtil.addToIdList(_detailIdList, _detailId);
        }
        try {
            // 一次审批
            saveUserPurIn(_userId, userName, stockNo, source, isBc, "");
        } catch(Exception e) {
            if (!VtuzxUtil.isEmpty(_detailIdList)) {
                purInDetailDao.deleteMany(Criteria.where(IVtuzxConst.Key__id).in(_detailIdList));
                purInDetailBoxDao.deleteMany(Criteria.where("_detailId").in(_detailIdList));
            }
            throw e;
        }
    }

    @Override
    public void saveUserPurIn(ObjectId _userId, String userName, String stockNo, String source, boolean isBc, String orderNo) throws Exception {
        String billNo = IXqcConst.createBillNo(BillType.CGRK);
        // 加人，时间，仓库，总箱数，总重量
        String supplierNo = "";
        String supplierName = "";
        Criteria opCond = Criteria.where("_createUserId").is(_userId).and("stockNo").is(stockNo).and("isTemp").is(true);
        if (isBc) {
            opCond.and("isBc").is(true);
        }
        Iterator<Document> detailItr = purInDetailBoxDao.findList(opCond, null, 0, 0);
        int boxCount = 0;
        double count = 0d;
        while(detailItr.hasNext()) {
            Document detail = detailItr.next();
            supplierNo = VtuzxUtil.getString(detail, "supplierNo");
            supplierName = VtuzxUtil.getString(detail, "supplierName");
            boxCount++;
            count += VtuzxUtil.getDouble(detail, "count");
        }
        Document purInDoc = new Document("billNo", billNo)
                .append("stockNo", stockNo)
                .append("boxCount", boxCount)
                .append("count", count)
                .append("supplierNo", supplierNo)
                .append("supplierName", supplierName)
                .append("status", BillStatus.Save.toString());
        if (isBc) {
            purInDoc.remove("supplierNo");
            purInDoc.remove("supplierName");
            purInDoc.append("isBc", true);
            purInDoc.append("orderNo", orderNo);
        }
        purInDao.insertBill(_userId, userName, purInDoc);
        try {
            Document detailUpdateVal = new Document("$set", new Document("billNo", billNo));
            detailUpdateVal.append("$unset", new Document("isTemp", 1));
            purInDetailDao.updateManyRedirect(opCond, detailUpdateVal);
            purInDetailBoxDao.updateManyRedirect(opCond, detailUpdateVal);
            if (VtuzxUtil.isEmpty(orderNo)) {
                auditPurInOrder(_userId, userName, stockNo, billNo, source, isBc);
            }
        } catch(Exception e) {
            Criteria rollbackCond = Criteria.where("billNo").is(billNo);
            purInDao.deleteOne(rollbackCond);
            purInDetailDao.updateManyRedirect(rollbackCond,
                    new Document("$set", new Document("isTemp", true)).append("$unset", new Document("billNo", 1)));
            purInDetailBoxDao.updateManyRedirect(rollbackCond,
                    new Document("$set", new Document("isTemp", true)).append("$unset", new Document("billNo", 1)));
            throw e;
        }
        //判断仓库是肖斌和冠冠的传
        if (stockNo.equals("030") || stockNo.equals("031") || stockNo.equals("032") || stockNo.equals("015") || stockNo.equals("011")){
            //采购04 05 06 09开头物料传入极客云
            Iterator<Document> purInDetailItr = purInDetailDao.findList(Criteria.where("billNo").is(billNo),null,0,0);
            List<VtuzxMap> materialNoList = new ArrayList<>();
            while (purInDetailItr.hasNext()){
                Document purInDetailDoc = purInDetailItr.next();
                String materialNo = VtuzxUtil.getString(purInDetailDoc,"materialNo");
                double inCount = VtuzxUtil.getDouble(purInDetailDoc,"count");
                if ( materialNo.startsWith("04") || materialNo.startsWith("05") || materialNo.startsWith("06") || materialNo.startsWith("09")){
                    VtuzxMap materialMap = new VtuzxMap();
                    materialMap.append("materialNo",materialNo)
                            .append("inCount",inCount);
                    materialNoList.add(materialMap);
                }
            }
            if (!VtuzxUtil.isEmpty(materialNoList)){//有符合的物料在传吉客云
                String intWarehouseCode = "XQWG00101";//仓库编码

                //获取令牌
                Document storeDoc = storeTokenDao.findOne(Criteria.where("type").is("kingdee"));
                //创建极客云入库单
                VtuzxMap stockParam = new VtuzxMap();//入库参数
                List<VtuzxMap> stockInDetailViews = new ArrayList<>();//入库申请单明细
                for (VtuzxMap material:materialNoList){
                    String materialNo = VtuzxUtil.getString(material,"materialNo");
                    double inCount = VtuzxUtil.getDouble(material,"inCount");
                    VtuzxMap goodsMap = new VtuzxMap();//getGoodsList方法返回值
                    //需要先获取条码(skubarcode)
                    VtuzxMap goodsParam = new VtuzxMap();
                    goodsParam.append("pageIndex",0)
                            .append("pageSize",1)
                            .append("goodsNo",materialNo);
                    try {
                        goodsMap = iJiKeYunApiService.getGoodsList(storeDoc, goodsParam);
                    } catch (Exception e){
                        throw new VtuzxException(e.getMessage());
                    }
                    LinkedHashMap result = VtuzxUtil.getObject(goodsMap,"result");
                    LinkedHashMap data = VtuzxUtil.getObject((Map<String, Object>) result,"data");
                    List<LinkedHashMap> goods = VtuzxUtil.getObject((Map<String, Object>) data,"goods");
                    LinkedHashMap goodsResult = null;
                    if (goods.size()>0){
                        goodsResult = goods.get(0);
                    }
                    String skuBarcode = VtuzxUtil.getString((Map<String, Object>) goodsResult,"skuBarcode");//条码
                    VtuzxMap stockInMap = new VtuzxMap();
                    stockInMap.append("relDetailId",billNo)
                            .append("skuCount",inCount)
                            .append("isCertified",1)
                            .append("skuBarcode",skuBarcode);
                    stockInDetailViews.add(stockInMap);
                }
                stockParam.append("inWarehouseCode",intWarehouseCode)
                        .append("memo",supplierNo + "," + supplierName)//备注传供应商编码和名称
                        .append("inType",101)
                        .append("relDataId",billNo)//关联单据编号,可随机，保证不重复即可
                        .append("applyDate",VtuzxUtil.formatYmdHmsF(new Date()))
                        .append("operator",userName)
                        .append("source","OPEN")
                        .append("notificationCode","100")
                        .append("stockInDetailViews",stockInDetailViews);
                try {
                    iJiKeYunApiService.createStockIn(storeDoc,stockParam);
                } catch (Exception e){
//                    throw new VtuzxException(e.getMessage());
                    _logger.info(e.getMessage());
                }
            }
        }

    }

    /**
     * 采购入库单审批
     *
     * @param _userId 用户ID
     * @param userName 用户名
     * @param stockNo 仓库编码
     * @param billNo 单据号
     * @throws VtuzxException 异常处理
     */
    @Override
    public void auditPurInOrder(ObjectId _userId, String userName, String stockNo, String billNo, String source, boolean isBc) throws VtuzxException {
        Criteria getCond = Criteria.where("billNo").is(billNo);
        Document purInDoc = purInDao.findOne(getCond);
        String orderNo = VtuzxUtil.getString(purInDoc, "orderNo");
        Iterator<Document> purInDetailItr = purInDetailDao.findList(getCond, null, 0, 0);
        Iterator<Document> purInDetailBoxItr = purInDetailBoxDao.findList(getCond, null, 0, 0);
        List<Document> purInDetailBoxList = new ArrayList<>();
        List<String> colBoxNoList = new ArrayList<>();
        while(purInDetailBoxItr.hasNext()) {
            Document document = purInDetailBoxItr.next();
            String boxNo = VtuzxUtil.getString(document, "boxNo");
            colBoxNoList.add(boxNo);
            purInDetailBoxList.add(document);
        }

        VtuzxMap updateColBillMap = new VtuzxMap();
        Iterator<Document> purColDetailItr = purColDetailDao.findList(Criteria.where("boxNo").in(colBoxNoList), null, 0, 0);
        while (purColDetailItr.hasNext()) {
            Document purColDetailDoc = purColDetailItr.next();
            double count = VtuzxUtil.getDouble(purColDetailDoc, "count");
            String colBillNo = VtuzxUtil.getString(purColDetailDoc, "billNo");
            VtuzxMap updateColBill = VtuzxUtil.getObject(updateColBillMap, colBillNo);
            if (VtuzxUtil.isEmpty(updateColBill)) {
                VtuzxMap smallColBillMap = new VtuzxMap();
                smallColBillMap.append("count", count).append("boxCount", 1);
                updateColBillMap.append(colBillNo, smallColBillMap);
            } else {
                double sCount = VtuzxUtil.getDouble(updateColBill, "count");
                int sBoxCount = VtuzxUtil.getInt(updateColBill, "boxCount");
                updateColBillMap.append(colBillNo, new VtuzxMap("count", sCount + count).append("boxCount", sBoxCount + 1));
            }

        }

        List<BillMaterial> purInDetailList = new ArrayList<>();
        List<String> boxNoList = new ArrayList<>();
        while(purInDetailItr.hasNext()) {
            Document purInDetail = purInDetailItr.next();
            BillMaterial billMaterial = new BillMaterial();
            ObjectId _purInDetailId = purInDetail.getObjectId(IVtuzxConst.Key__id);
            billMaterial.setMaterialNo(VtuzxUtil.getString(purInDetail, "materialNo"));
            billMaterial.setUnit(VtuzxUtil.getString(purInDetail, "unit"));
            billMaterial.setBatchNo(VtuzxUtil.getString(purInDetail, "batchNo"));
            billMaterial.setProduceDate(VtuzxUtil.getString(purInDetail, "produceDate"));
            billMaterial.setExp(VtuzxUtil.getInt(purInDetail, "exp"));
            List<BillMaterialBox> boxList = new ArrayList<>();
            for(Document boxDoc: purInDetailBoxList) {
                ObjectId _detailId = VtuzxUtil.getObject(boxDoc, "_detailId");
                String barcodeType = VtuzxUtil.getString(boxDoc, "barcodeType");
                if (_purInDetailId.equals(_detailId)) {
                    BillMaterialBox box = new BillMaterialBox();
                    String boxNo = VtuzxUtil.getString(boxDoc, "boxNo");
                    box.setBoxNo(boxNo);
                    box.setRfid(VtuzxUtil.getString(boxDoc, "rfid"));
                    box.setCount(VtuzxUtil.getDouble(boxDoc, "count"));
                    box.setLocationNo(VtuzxUtil.getString(purInDetail, "locationNo"));
                    boxList.add(box);
                    if (!"BC".equals(barcodeType)) {
                        boxNoList.add(boxNo);
                    }
                }
                billMaterial.setBoxList(boxList);
            }
            purInDetailList.add(billMaterial);
        }
        purInDao.audit(_userId, userName, billNo);
        // 更新收货单入库状态
        if (!VtuzxUtil.isEmpty(boxNoList)) {
            try {
                UpdateResult updRes = purColDetailDao.updateMany(Criteria.where("boxNo").in(boxNoList).and("inStock").ne(true),
                        new Document("perInBillNo", billNo).append("perInTime", new Date()).append("inStock", true));
                if (updRes.getModifiedCount() != boxNoList.size()) {
                    throw new VtuzxException(IXqcConst.Msg_E_XQC_stock_pur_col_in_stock);
                }
            } catch (Exception e) {
                purColDetailDao.updateManyRedirect(Criteria.where("boxNo").in(boxNoList),
                        new Document("$unset", new Document("perInBillNo", 1).append("perInTime", 1).append("inStock", 1)));
                purInDao.unaudit(billNo);
                throw e;
            }
        }
        // 更新即时库存
        try {
            inventoryService.addInventory(_userId, userName, BillEvent.Audit, BillType.CGRK, stockNo, billNo, purInDetailList);

        } catch(Exception e) {
            purInDao.unaudit(billNo);
            if (!VtuzxUtil.isEmpty(boxNoList)) {
                purColDetailDao.updateManyRedirect(Criteria.where("boxNo").in(boxNoList),
                        new Document("$unset", new Document("perInBillNo", 1).append("perInTime", 1).append("inStock", 1)));
            }
            throw e;
        }
        //做收货单的已入库数量重量的反写
        updateColBillMap.forEach((k, v) -> {
            VtuzxMap map = (VtuzxMap) v;
            double sCount = VtuzxUtil.getDouble(map, "count");
            int sBoxCount = VtuzxUtil.getInt(map, "boxCount");
            purColDao.updateOneRedirect(Criteria.where("billNo").is(k), new Document("$inc", new Document("inStockCount", sCount).append("inStockBoxCount", sBoxCount)));
        });
        try {
            if (isBc) {
                syncKingdeeOrderService.syncPurOrderInStock(_userId, userName, billNo, orderNo, source);
            } else {
                syncKingdeeOrderService.syncPurInOrder(_userId, userName, billNo, "pda");
            }
        } catch (Exception e) {
            _logger.error(e.getMessage(), e);
        }

    }

    @Override
    public VtuzxMap addUserPurInMaterialBoxList(ObjectId _userId, String userName, String stockNo, String locationNo, List<Map<String, Object>> boxList, boolean isBc, String orderNo, String billNo) {
        List<String> excList = new ArrayList<>();
        for(Map<String, Object> box: boxList) {
            String boxNo = VtuzxUtil.getString(box, "boxNo");
            double count = VtuzxUtil.getDouble(box, "count");
            try {
                VtuzxMap purColDetail = getPurColMaterial(boxNo);
                addUserPurInMaterialBoxInner(purColDetail, _userId, userName, stockNo, locationNo, boxNo, count, isBc, orderNo, billNo);
            } catch(Exception e) {
                _logger.info("addUserPurInMaterialBoxList error:" + e.getMessage());
                excList.add(e.getMessage());
            }
        }
        return getUserPurInMaterial(_userId, stockNo, false, "", excList, "");
    }

    @Override
    public VtuzxMap addUserPurInMaterialBox(ObjectId _userId, String userName, String stockNo, String locationNo, String boxNo, double count) throws VtuzxException {
        VtuzxMap purColDetail = getPurColMaterial(boxNo);
        ObjectId _detailId = addUserPurInMaterialBoxInner(purColDetail, _userId, userName, stockNo, locationNo, boxNo, count, false, "", "");
        Document purInDetailDoc = purInDetailDao.findById(_detailId);
        return new VtuzxMap("boxCount", VtuzxUtil.getObject(purInDetailDoc, "boxCount"))
                .append("count", VtuzxUtil.getObject(purInDetailDoc, "count"))
                .append("colBoxCount", VtuzxUtil.getObject(purColDetail, "boxCount"))
                .append("colCount", VtuzxUtil.getObject(purColDetail, "count"));
    }

    /**
     * 采购入库增加临时箱号内部方法
     * @param purColDetail 收货单详细
     * @param _userId 用户ID
     * @param userName 用户名
     * @param stockNo 仓库编码
     * @param locationNo 仓位编码
     * @param boxNo 箱号
     * @param count 数量
     * @return 信息ID
     * @throws VtuzxException 异常处理
     */
    public ObjectId addUserPurInMaterialBoxInner(VtuzxMap purColDetail, ObjectId _userId, String userName, String stockNo, String locationNo, String boxNo, double count, boolean isBc, String orderNo, String bcPurInBillNo) throws VtuzxException {

        String barcodeType = VtuzxUtil.getString(purColDetail, "barcodeType");
        if ("BC".equals(barcodeType)) {
            boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
            boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
            boxNo = boxNo.substring(0, boxNo.lastIndexOf("|;"));
            boxNo = boxNo + "|;batch";
        } else {
            Document scanBoxDoc = purInDetailBoxDao.findOne(Criteria.where("boxNo").is(boxNo));
            if (scanBoxDoc != null) {
                throw new VtuzxException("箱号已入库!");
            }
        }

        String billNo = VtuzxUtil.getString(purColDetail, "billNo");
        String materialNo = VtuzxUtil.getString(purColDetail, "materialNo");
        String materialName = VtuzxUtil.getString(purColDetail, "materialName");
        String materialSpec = VtuzxUtil.getString(purColDetail, "materialSpec");
        String batchNo = "";
        if ("BC".equals(barcodeType)){
            batchNo = "*";
        } else {
            batchNo = VtuzxUtil.getString(purColDetail, "batchNo");
        }

        String supplierNo = VtuzxUtil.getString(purColDetail, "supplierNo");
        String supplierName = VtuzxUtil.getString(purColDetail, "supplierName");
        String rfid = VtuzxUtil.getString(purColDetail, "rfid");
        String produceDate = VtuzxUtil.getString(purColDetail, "produceDate");
        int exp = VtuzxUtil.getInt(purColDetail, "exp");
        String unit = VtuzxUtil.getString(purColDetail, "unit");
        int colBoxCount = VtuzxUtil.getInt(purColDetail, "boxCount");
        double colCount = VtuzxUtil.getDouble(purColDetail, "countTotal");

        if (isBc) {
            List<String> materialList = new ArrayList<>();
            Iterator<Document> purOrderDetailItr = purOrderDetailDao.findList(Criteria.where("orderNo").is(orderNo), null, 0, 0);
            while (purOrderDetailItr.hasNext()) {
                Document purOrderDetailDoc = purOrderDetailItr.next();
                String detailMaterialNo = VtuzxUtil.getString(purOrderDetailDoc, "materialNo");
                materialList.add(detailMaterialNo);
            }
            if (!materialList.contains(materialNo)) {
                throw new VtuzxException(String.format("物料【%s】不是采购订单内的物料", materialNo));
            }
        }

        Criteria detailCond = Criteria.where("_createUserId").is(_userId);
        detailCond.and("isTemp").is(true);
        detailCond.and("stockNo").is(stockNo);
        detailCond.and("locationNo").is(locationNo);
        detailCond.and("materialNo").is(materialNo);
        detailCond.and("batchNo").is(batchNo);
        detailCond.and("produceDate").is(produceDate);
        detailCond.and("billNo").is(billNo);
        detailCond.and("exp").is(exp);
        detailCond.and("unit").is(unit);
        if (isBc) {
            detailCond.and("isBc").is(true);
        }
        Document detail = purInDetailDao.findOne(detailCond);
        Document updateVal = new Document();

        double nowColCount = 0.0;
        int nowColBoxCount = 0;
        if ("BC".equals(barcodeType)) {
            nowColCount = count;
            nowColBoxCount = 1;
        } else {
            Iterator<Document> purColDetailItr = purColDetailDao.findList(Criteria.where("billNo").is(billNo), new Document("createTime", -1), 0, 0);
            while (purColDetailItr.hasNext()) {
                Document purColDetailDoc = purColDetailItr.next();
                boolean inStock = VtuzxUtil.getBoolean(purColDetailDoc, "inStock");
                double purColCount = VtuzxUtil.getDouble(purColDetailDoc, "count");
                if (!inStock) {
                    nowColCount += purColCount;
                    nowColBoxCount++;
                }
            }
        }
        if (detail == null) {
            if (VtuzxUtil.isEmpty(bcPurInBillNo)) {
                updateVal.append("isTemp", true);
            } else {
                updateVal.append("billNo", bcPurInBillNo);
            }
            updateVal.append("stockNo", stockNo);
            updateVal.append("locationNo", locationNo);
            updateVal.append("materialNo", materialNo);
            updateVal.append("materialName", materialName);
            updateVal.append("materialSpec", materialSpec);
            updateVal.append("unit", unit);
            updateVal.append("batchNo", batchNo);
            updateVal.append("produceDate", produceDate);
            updateVal.append("exp", exp);
            updateVal.append("_createUserId", _userId);
            updateVal.append("createUserName", userName);
            updateVal.append("boxCount", 1);
            updateVal.append("count", count);
            updateVal.append("colCount", colCount);
            updateVal.append("colBoxCount", colBoxCount);
            updateVal.append("nowColCount", nowColCount);
            updateVal.append("supplierNo", supplierNo);
            updateVal.append("supplierName", supplierName);
            updateVal.append("nowColBoxCount", nowColBoxCount);
            if (isBc) {
                updateVal.append("isBc", true);
                updateVal.append("orderNo", orderNo);
            }
            if (!VtuzxUtil.isEmpty(bcPurInBillNo)) {
                purInDao.updateOneRedirect(Criteria.where("billNo").is(bcPurInBillNo), new Document("$inc", new Document("boxCount", 1).append("count", count)).append("$set", new Document("nowColCount", nowColCount).append("nowColBoxCount", nowColBoxCount)));
            }
        } else {
            updateVal = new Document("$inc", new Document("boxCount", 1).append("count", count)).append("$set", new Document("nowColCount", nowColCount).append("nowColBoxCount", nowColBoxCount));

        }
        ObjectId _detailId;
        if (detail == null) {
            _detailId = purInDetailDao.insertOne(updateVal);
        } else {
            _detailId = VtuzxUtil.getObject(detail, IVtuzxConst.Key__id);
            purInDetailDao.updateByIdRedirect(_detailId, updateVal);
        }
        Document detailBox = new Document();
        if (VtuzxUtil.isEmpty(bcPurInBillNo)) {
            detailBox.append("isTemp", true);
        } else {
            detailBox.append("billNo", bcPurInBillNo);
        }
        detailBox.append("_detailId", _detailId);
        detailBox.append("boxNo", boxNo);
        detailBox.append("rfid", rfid);
        detailBox.append("count", count);
        detailBox.append("unit", unit);
        detailBox.append("supplierName", supplierName);
        detailBox.append("supplierNo", supplierNo);
        detailBox.append("_createUserId", _userId);
        detailBox.append("createUserName", userName);
        detailBox.append("stockNo", stockNo);
        detailBox.append("barcodeType", barcodeType);
        if (isBc) {
            detailBox.append("isBc", true);
            detailBox.append("orderNo", orderNo);
        }
        purInDetailBoxDao.insertOne(detailBox);
        return _detailId;
    }

    @Override
    public VtuzxMap deleteUserPurInMaterialBox(ObjectId _userId, String id) {
        Document purInDetailBoxDoc = purInDetailBoxDao.findOne(Criteria.where("_id").is(FastUtil.convertId(id)));
        ObjectId _detailId = VtuzxUtil.getObject(purInDetailBoxDoc, "_detailId");
        String billNo = VtuzxUtil.getString(purInDetailBoxDoc, "billNo");
        if (!VtuzxUtil.isEmpty(billNo)) {
            double count = VtuzxUtil.getDouble(purInDetailBoxDoc, "count");
            purInDao.updateOneRedirect(Criteria.where("billNo").is(billNo), new Document("$inc", new Document("count", -count).append("boxCount", -1)));
            Document purInDoc = purInDao.findOne(Criteria.where("billNo").is(billNo));
            double purInCount = VtuzxUtil.getDouble(purInDoc, "count");
            if (purInCount == 0) {
                purInDao.deleteOne(Criteria.where("billNo").is(billNo));
            }
        }
        purInDetailBoxDao.deleteById(FastUtil.convertId(id));
        Iterator<Document> purInDetailBoxItr = purInDetailBoxDao.findList(Criteria.where("_detailId").is(_detailId), null, 0, 0);
        int boxCount = 0;
        double total = 0;
        while(purInDetailBoxItr.hasNext()) {
            Document doc = purInDetailBoxItr.next();
            double purInDetailBoxCount = VtuzxUtil.getDouble(doc, "count");
            total = purInDetailBoxCount + total;
            boxCount++;
        }
        if (boxCount == 0) {
            purInDetailDao.deleteById(_detailId);
        } else {
            purInDetailDao.updateById(_detailId, new Document("boxCount", boxCount).append("count", total));
        }
        return new VtuzxMap("count", total).append("boxCount", boxCount);
    }

    @Override
    public void deleteUserPurInMaterial(ObjectId _userId, String id) {
        Document detailDoc = purInDetailDao.findById(id);
        String billNo = VtuzxUtil.getString(detailDoc, "billNo");
        if (!VtuzxUtil.isEmpty(billNo)) {
            double count = VtuzxUtil.getDouble(detailDoc, "count");
            int boxCount = VtuzxUtil.getInt(detailDoc, "boxCount");
            purInDao.updateOneRedirect(Criteria.where("billNo").is(billNo), new Document("$inc", new Document("count", -count).append("boxCount", -boxCount)));
            Document purInDoc = purInDao.findOne(Criteria.where("billNo").is(billNo));
            double purInCount = VtuzxUtil.getDouble(purInDoc, "count");
            if (purInCount == 0) {
                purInDao.deleteOne(Criteria.where("billNo").is(billNo));
            }
        }
        purInDetailDao.deleteById(FastUtil.convertId(id));
        purInDetailBoxDao.deleteMany(Criteria.where("_detailId").is(FastUtil.convertId(id)));
    }

    @Override
    public void deleteUserPurIn(ObjectId _userId, String stockNo) {
        Criteria cond = Criteria.where("_createUserId").is(_userId).and("stockNo").is(stockNo).and("isTemp").is(true);
        purInDetailDao.deleteMany(cond);
        purInDetailBoxDao.deleteMany(cond);
    }

    @Override
    public VtuzxMap updateUserPurInMaterialBox(ObjectId _userId, String boxNo, double count) {
        Criteria cond = Criteria.where("_createUserId").is(_userId).and("boxNo").is(boxNo).and("isTemp").is(true);
        Document detailBoxDoc = purInDetailBoxDao.findOne(cond);
        String stockNo = VtuzxUtil.getString(detailBoxDoc, "stockNo");
        ObjectId _detailId = VtuzxUtil.getObject(detailBoxDoc, "_detailId");
        purInDetailBoxDao.updateOne(cond, new Document("count", count));
        Iterator<Document> purInDetailBoxItr = purInDetailBoxDao.findList(Criteria.where("_createUserId").is(_userId).and("stockNo").is(stockNo).and("isTemp").is(true), new Document("stockNo", 1), 0, 0);
        int boxCount = 0;
        double total = 0;
        while(purInDetailBoxItr.hasNext()) {
            Document doc = purInDetailBoxItr.next();
            double purInDetailBoxCount = VtuzxUtil.getDouble(doc, "count");
            total = purInDetailBoxCount + total;
            boxCount++;
        }
        purInDetailDao.updateById(_detailId, new Document("boxCount", boxCount).append("count", total));
        return new VtuzxMap("count", total).append("boxCount", boxCount);
    }

    @Override
    public VtuzxMap getUserPurInMaterial(ObjectId _userId, String stockNo, boolean isBc, String orderNo, List<String> excList, String billNo) {
        List<VtuzxMap> purInDetailList = new ArrayList<>();
        Criteria cond = new Criteria("_createUserId").is(_userId).and("stockNo").is(stockNo);
        if (VtuzxUtil.isEmpty(billNo)) {
            cond.and("isTemp").is(true);
        } else {
            cond.and("billNo").is(billNo);
        }
        if (isBc) {
            cond.and("isBc").is(true);
            cond.and("orderNo").is(orderNo);
        } else {
            cond.and("isBc").ne(true);
        }
        Iterator<Document> purInDetailItr = purInDetailDao.findList(cond, null, 0, 0);
        while (purInDetailItr.hasNext()) {
            Document purInDetailDoc = purInDetailItr.next();
            VtuzxMap purInDetailMap = new VtuzxMap(purInDetailDoc);
            purInDetailMap.remove(IVtuzxConst.Key_createTime);
            purInDetailMap.remove(IVtuzxConst.Key_updateTime);
            purInDetailMap.remove("_createUserId");
            purInDetailMap.remove("createUserName");
            purInDetailMap.remove("_updateUserId");
            purInDetailMap.remove("updateUserName");
            purInDetailMap.append("id", VtuzxUtil.removeString(purInDetailMap, IVtuzxConst.Key__id));
            purInDetailList.add(purInDetailMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, purInDetailList).append("excList", excList);
    }

    @Override
    public VtuzxMap getUserPurInMaterialBox(ObjectId _userId, String detailId, String billNo) {
        Criteria cond = Criteria.where("_createUserId").is(_userId).and("_detailId").is(FastUtil.convertId(detailId));
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").is(billNo);
        } else {
            cond.and("isTemp").is(true);
        }
        Iterator<Document> purInDetailBoxItr = purInDetailBoxDao.findList(cond, null, 0, 0);
        List<VtuzxMap> dataList = new ArrayList<>();
        while (purInDetailBoxItr.hasNext()) {
            Document boxDoc = purInDetailBoxItr.next();
            VtuzxMap boxMap = new VtuzxMap(boxDoc);
            boxMap.remove(IVtuzxConst.Key_createTime);
            boxMap.remove(IVtuzxConst.Key_updateTime);
            boxMap.remove("_createUserId");
            boxMap.remove("createUserName");
            boxMap.remove("_updateUserId");
            boxMap.remove("updateUserName");
            boxMap.append("id", VtuzxUtil.removeString(boxMap, IVtuzxConst.Key__id));
            dataList.add(boxMap);
        }

        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
     }


    @Override
    public VtuzxMap getPurInBill(ObjectId _userId, int pageIndex, int pageSize, Map<String, Object> param) {
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        String type = VtuzxUtil.getString(param, "type");
        String billNo = VtuzxUtil.getString(param, "billNo");
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");


        Criteria cond = new Criteria();
        cond.and("count").ne(0);
        List<VtuzxMap> dataList = new ArrayList<>();
        if (!VtuzxUtil.isEmpty(stockNo)) {
            cond.and("stockNo").is(stockNo);
        }
        if (!VtuzxUtil.isEmpty(type)) {
            cond.and("isBc").is(true);
        } else {
            cond.and("isBc").ne(true);
        }
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        if (!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo) || !VtuzxUtil.isEmpty(boxNo)) {
            List<String> inBillNoList = new ArrayList<>();
            if (!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo)) {
                Criteria smallCond = new Criteria();
                if (!VtuzxUtil.isEmpty(materialNo)) {
                    smallCond.and("materialNo").is(materialNo);
                }
                if (!VtuzxUtil.isEmpty(batchNo)) {
                    smallCond.and("batchNo").regex(batchNo);
                }
                Iterator<Document> purInDetailItr = purInDetailDao.findList(smallCond, null, 0, 0);
                while (purInDetailItr.hasNext()) {
                    Document purInDetailDoc = purInDetailItr.next();
                    String purInBillNo = VtuzxUtil.getString(purInDetailDoc, "billNo");
                    inBillNoList.add(purInBillNo);
                }
            } else {
                Iterator<Document> boxItr = purInDetailBoxDao.findList(Criteria.where("boxNo").is(boxNo),null, 0, 0);
                while (boxItr.hasNext()) {
                    Document boxDoc = boxItr.next();
                    inBillNoList.add(VtuzxUtil.getString(boxDoc, "billNo"));
                }
            }

            Iterator<Document> purInItr = purInDao.findList(Criteria.where("billNo").in(inBillNoList), null, 0, 0);
            while (purInItr.hasNext()) {
                Document purInDoc = purInItr.next();
                VtuzxMap purInMap = new VtuzxMap(purInDoc);
                purInMap.append("id", VtuzxUtil.removeString(purInMap, IVtuzxConst.Key__id));
                purInMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(purInMap, "createTime")));
                dataList.add(purInMap);
            }
            return new VtuzxMap(IVtuzxConst.Key_data, dataList);
        }
        VtuzxPage page = purInDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("status", VtuzxUtil.getString(doc, "status"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime")))
                .append("stockNo", VtuzxUtil.getString(doc, "stockNo"))
                .append("boxCount", VtuzxUtil.getInt(doc, "boxCount"))
                .append("count", VtuzxUtil.getDouble(doc, "count")));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPurInBillBn(ObjectId _userId, int pageIndex, int pageSize, Map<String, Object> param) {
        // 获取参数中的stockNo
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        // 获取参数中的type
        String type = VtuzxUtil.getString(param, "type");
        // 获取参数中的billNo
        String billNo = VtuzxUtil.getString(param, "billNo");
        // 获取参数中的materialNo
        String materialNo = VtuzxUtil.getString(param, "materialNo");
        // 获取参数中的batchNo
        String batchNo = VtuzxUtil.getString(param, "batchNo");
        // 获取参数中的boxNo
        String boxNo = VtuzxUtil.getString(param, "boxNo");
        // 获取参数中的createUserName
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        // 获取参数中的createTime
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        // 查询所有含BN批次的订单号
        Set<String> bnBillNoSet = new HashSet<>();
        // 使用正则查询所有批次号以BN开头的采购明细
        Iterator<Document> bnDetailItr = purInDetailDao.findList(
                Criteria.where("batchNo").regex("^BN.*"),
                null, 0, 0
        );
        // 遍历bnDetailItr，将每个元素的"billNo"字段添加到bnBillNoSet中
        while (bnDetailItr.hasNext()) {
            bnBillNoSet.add(VtuzxUtil.getString(bnDetailItr.next(), "billNo"));
        }
        // 在构建bnBillNoSet后，立即根据搜索框的billNo过滤
        if (!VtuzxUtil.isEmpty(billNo)) {
            // 使用正则表达式预过滤bnBillNoSet，保留匹配搜索框输入的billNo
            Pattern pattern = Pattern.compile(".*" + billNo + ".*", Pattern.CASE_INSENSITIVE);
            bnBillNoSet = bnBillNoSet.stream()
                    .filter(bn -> pattern.matcher(bn).find())
                    .collect(Collectors.toSet());
        }
        // 无有效BN订单时直接返回空（避免后续查询）
        if (bnBillNoSet.isEmpty()) {
            return new VtuzxMap(IVtuzxConst.Key_total, 0).append(IVtuzxConst.Key_data, new ArrayList<>());
        }
        // 创建一个Criteria对象
        Criteria cond = new Criteria();
        // 添加条件，count不等于0
        cond.and("count").ne(0);
        // x查询条件添加BN订单过滤
        cond.and("billNo").in(bnBillNoSet);
        // 创建一个List，用于存储VtuzxMap对象
        List<VtuzxMap> dataList = new ArrayList<>();
        // 如果stockNo不为空，则将stockNo添加到条件中
        if (!VtuzxUtil.isEmpty(stockNo)) {
            cond.and("stockNo").is(stockNo);
        }
        // 如果type不为空，则将isBc添加到条件中
        if (!VtuzxUtil.isEmpty(type)) {
            cond.and("isBc").is(true);
        } else {
            // 否则将isBc添加到条件中，但不等于true
            cond.and("isBc").ne(true);
        }
        // 如果billNo不为空，则将billNo添加到条件中
        /*if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }*/
        // 如果createUserName不为空，则将createUserName添加到条件中
        if (!VtuzxUtil.isEmpty(createUserName)) {
            // 将createUserName按照逗号分隔，得到一个数组
            String[] splitList = createUserName.split("，");
            // 如果数组长度为1，则将createUserName添加到条件中
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                // 否则将数组转成list，并将createUserName添加到条件中
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        // 判断createTime是否为空
        if (!VtuzxUtil.isEmpty(createTime)) {
            // 如果不为空，则将createTime的起始时间和结束时间转换为Date类型，并添加到查询条件中
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        // 判断materialNo、batchNo、boxNo是否为空，如果不为空，则执行以下操作
        if (!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo) || !VtuzxUtil.isEmpty(boxNo)) {
            // 创建一个空的List，用于存储查询到的billNo
            List<String> inBillNoList = new ArrayList<>();
            // 判断materialNo、batchNo是否为空，如果不为空，则执行以下操作
            if (!VtuzxUtil.isEmpty(materialNo) || !VtuzxUtil.isEmpty(batchNo)) {
                // 创建一个Criteria对象，用于查询
                Criteria smallCond = new Criteria();
                // 如果materialNo不为空，则将materialNo添加到Criteria中
                if (!VtuzxUtil.isEmpty(materialNo)) {
                    smallCond.and("materialNo").is(materialNo);
                }
                // 如果batchNo不为空，则将batchNo添加到Criteria中
                if (!VtuzxUtil.isEmpty(batchNo)) {
                    smallCond.and("batchNo").regex(batchNo);
                }
                // 根据Criteria查询purInDetail表，获取结果集
                Iterator<Document> purInDetailItr = purInDetailDao.findList(smallCond, null, 0, 0);
                // 遍历结果集
                while (purInDetailItr.hasNext()) {
                    // 获取结果集中的Document对象
                    Document purInDetailDoc = purInDetailItr.next();
                    // 获取billNo，并将其添加到List中
                    String purInBillNo = VtuzxUtil.getString(purInDetailDoc, "billNo");
                    inBillNoList.add(purInBillNo);
                }
            // 如果materialNo、batchNo为空，则执行以下操作
            } else {
                // 根据boxNo查询purInDetailBox表，获取结果集
                Iterator<Document> boxItr = purInDetailBoxDao.findList(Criteria.where("boxNo").is(boxNo),null, 0, 0);
                // 遍历结果集
                while (boxItr.hasNext()) {
                    // 获取结果集中的Document对象
                    Document boxDoc = boxItr.next();
                    // 获取billNo，并将其添加到List中
                    inBillNoList.add(VtuzxUtil.getString(boxDoc, "billNo"));
                }
            }
            // 只保留包含BN批次的订单
            inBillNoList = inBillNoList.stream()
                    .filter(bnBillNoSet::contains)
                    .collect(Collectors.toList());
            // 无有效数据时直接返回空
            if (inBillNoList.isEmpty()) {
                return new VtuzxMap(IVtuzxConst.Key_data, new ArrayList<>());
            }
            // 从purInDao中查找billNo在inBillNoList中的记录
            Iterator<Document> purInItr = purInDao.findList(Criteria.where("billNo").in(inBillNoList), null, 0, 0);
            // 遍历查找结果
            while (purInItr.hasNext()) {
                // 获取下一个记录
                Document purInDoc = purInItr.next();
                // 将记录转换为VtuzxMap对象
                VtuzxMap purInMap = new VtuzxMap(purInDoc);
                // 将id字段从VtuzxMap中移除，并添加到dataList中
                purInMap.append("id", VtuzxUtil.removeString(purInMap, IVtuzxConst.Key__id));
                // 将createTime字段格式化为yyyy-MM-dd HH:mm:ss.SSS，并添加到dataList中
                purInMap.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(purInMap, "createTime")));
                dataList.add(purInMap);
            }
            // 创建一个新的VtuzxMap对象，key为IVtuzxConst.Key_data，value为dataList
            return new VtuzxMap(IVtuzxConst.Key_data, dataList);
        }
        // 根据条件、排序、分页查询数据
        VtuzxPage page = purInDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        // 将查询结果转换为VtuzxMap对象
        dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("status", VtuzxUtil.getString(doc, "status"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime")))
                .append("stockNo", VtuzxUtil.getString(doc, "stockNo"))
                .append("boxCount", VtuzxUtil.getInt(doc, "boxCount"))
                .append("count", VtuzxUtil.getDouble(doc, "count")));
        // 返回结果，包含总记录数和数据列表
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPurInBillDetail(ObjectId _userId, String stockNo, String billNo) {
        Document purInDoc = purInDao.findOne(Criteria.where("billNo").is(billNo).and("stockNo").is(stockNo));
        String createUserName = VtuzxUtil.getString(purInDoc, "createUserName");
        int boxCount = VtuzxUtil.getInt(purInDoc, "boxCount");
        double count = VtuzxUtil.getDouble(purInDoc, "count");
        String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(purInDoc, "createTime"));
        VtuzxMap header = new VtuzxMap("billNo", billNo)
                .append("createUserName", createUserName)
                .append("createTime", createTime)
                .append("stockNo", stockNo)
                .append("boxCount", boxCount)
                .append("count", count);

        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> purInDetailItr = purInDetailDao.findList(Criteria.where("billNo").is(billNo).and("stockNo").is(stockNo), null, 0, 0);
        while (purInDetailItr.hasNext()) {
            Document purInDetailDoc = purInDetailItr.next();
            VtuzxMap purInDetailMap = new VtuzxMap(purInDetailDoc);
            String materialNo = VtuzxUtil.getString(purInDetailMap, "materialNo");
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            String fBaseUnitIdFName = VtuzxUtil.getString(materialDoc, "fBaseUnitIdFName");
            purInDetailMap.remove(IVtuzxConst.Key_createTime);
            purInDetailMap.remove(IVtuzxConst.Key_updateTime);
            purInDetailMap.remove("_createUserId");
            purInDetailMap.remove("createUserName");
            purInDetailMap.remove("_updateUserId");
            purInDetailMap.remove("updateUserName");
            purInDetailMap.append("id", VtuzxUtil.removeString(purInDetailMap, IVtuzxConst.Key__id));
            purInDetailMap.append("unit", fBaseUnitIdFName);
            dataList.add(purInDetailMap);
        }
        return new VtuzxMap("header", header).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPurInBillDetailBn(ObjectId _userId, String stockNo, String billNo) {
        Document purInDoc = purInDao.findOne(Criteria.where("billNo").is(billNo).and("stockNo").is(stockNo));
        String createUserName = VtuzxUtil.getString(purInDoc, "createUserName");
        int boxCount = VtuzxUtil.getInt(purInDoc, "boxCount");
        double count = VtuzxUtil.getDouble(purInDoc, "count");
        String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(purInDoc, "createTime"));
        VtuzxMap header = new VtuzxMap("billNo", billNo)
                .append("createUserName", createUserName)
                .append("createTime", createTime)
                .append("stockNo", stockNo)
                .append("boxCount", boxCount)
                .append("count", count);

        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> purInDetailItr = purInDetailDao.findList(Criteria.where("billNo").is(billNo).and("stockNo").is(stockNo), null, 0, 0);
        while (purInDetailItr.hasNext()) {
            Document purInDetailDoc = purInDetailItr.next();
            VtuzxMap purInDetailMap = new VtuzxMap(purInDetailDoc);
            String materialNo = VtuzxUtil.getString(purInDetailMap, "materialNo");
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            String fBaseUnitIdFName = VtuzxUtil.getString(materialDoc, "fBaseUnitIdFName");
            purInDetailMap.remove(IVtuzxConst.Key_createTime);
            purInDetailMap.remove(IVtuzxConst.Key_updateTime);
            purInDetailMap.remove("_createUserId");
            purInDetailMap.remove("createUserName");
            purInDetailMap.remove("_updateUserId");
            purInDetailMap.remove("updateUserName");
            purInDetailMap.append("id", VtuzxUtil.removeString(purInDetailMap, IVtuzxConst.Key__id));
            purInDetailMap.append("unit", fBaseUnitIdFName);
            dataList.add(purInDetailMap);
        }
        return new VtuzxMap("header", header).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPurInBillDetailBox(ObjectId _userId, String detailId) {
        Criteria cond = Criteria.where("_detailId").is(FastUtil.convertId(detailId));
        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> purInDetailBoxItr = purInDetailBoxDao.findList(cond, null, 0, 0);
        while (purInDetailBoxItr.hasNext()) {
            Document boxDoc = purInDetailBoxItr.next();
            VtuzxMap boxMap = new VtuzxMap(boxDoc);
            boxMap.remove(IVtuzxConst.Key_createTime);
            boxMap.remove(IVtuzxConst.Key_updateTime);
            boxMap.remove("_createUserId");
            boxMap.remove("createUserName");
            boxMap.remove("_updateUserId");
            boxMap.remove("updateUserName");
            boxMap.append("id", VtuzxUtil.removeString(boxMap, IVtuzxConst.Key__id));
            dataList.add(boxMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }


    @Override
    public VtuzxMap getCreatedBcPurInList(ObjectId userId, String orderNo) {
        List<Document> dataList = new ArrayList<>();
        Iterator<Document> purInDocItr = purInDao.findList(Criteria.where("orderNo").is(orderNo).and("status").is("save"), new Document("createTime", -1), 0, 0);
        while (purInDocItr.hasNext()) {
            Document purInDoc = purInDocItr.next();
            dataList.add(purInDoc);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPurInBillByBillNo(ObjectId userId, String billNo) throws VtuzxException{
        //判断一下单据编号是否正确
        if (!billNo.startsWith("CGRK")){
            throw new VtuzxException("单据格式错误");
        }
        Iterator<Document> purInDetailItr = purInDetailDao.findList(Criteria.where("billNo").is(billNo),null,0,0);
        List<Document> purInDetailList = new ArrayList<>();
        while (purInDetailItr.hasNext()){
            Document purInDetailDoc = purInDetailItr.next();
            ObjectId _id = VtuzxUtil.getObject(purInDetailDoc,"_id");
            Document detailBoxDoc = purInDetailBoxDao.findOne(Criteria.where("_detailId").is(_id));
            String boxNo = VtuzxUtil.getString(detailBoxDoc,"boxNo");
            String barcodeType = VtuzxUtil.getString(detailBoxDoc,"barcodeType");
            purInDetailDoc.append("boxNo",boxNo)
                    .append("barcodeType",barcodeType);
            purInDetailList.add(purInDetailDoc);
        }
        return new VtuzxMap("data",purInDetailList);
    }

    @Override
    public void addPurReturn(String name, ObjectId userId, Map<String, Object> param) throws Exception {
        String billNo = IXqcConst.createBillNo(BillType.CGTH);

        List<Document> purReturnList = VtuzxUtil.getObject(param,"purList");
        if (purReturnList == null || purReturnList.size() == 0){
            throw new VtuzxException("暂无数据,无法生成退货单");
        }
        String prdInBillNo = VtuzxUtil.getString(purReturnList.get(0),"billNo");//对应入库单号
        String supplierNo = VtuzxUtil.getString(purReturnList.get(0),"supplierNo");//供应商编号
        String supplierName = VtuzxUtil.getString(purReturnList.get(0),"supplierName");//供应商姓名
        List<Document> detailList = new ArrayList<>();//添加到详情表的数据
        //循环集合先添加详情数据
        double count = 0;//退货总数量
        int boxCount = 0;//退货总箱数

        List<VtuzxMap> bcBoxList = new ArrayList<>();//包材出库
        List<String> boxNoList = new ArrayList<>();
        String stockNo = VtuzxUtil.getString(purReturnList.get(0),"stockNo");
        for (Map<String,Object> data : purReturnList){
            Document detailDoc = new Document();
            double returnCount = VtuzxUtil.getDouble(data,"returnCount");

            if(returnCount > 0){
                String barcodeType = VtuzxUtil.getString(data,"barcodeType");
                String boxNo = VtuzxUtil.getString(data,"boxNo");
                String locationNo = VtuzxUtil.getString(data,"locationNo");
                if ("BC".equals(barcodeType)){
                    bcBoxList.add(new VtuzxMap("boxNo",boxNo).append("count", BigDecimal.valueOf(returnCount).setScale(0, RoundingMode.HALF_UP).intValue())
                    .append("locationNo",locationNo));
                } else {
                    boxNoList.add(boxNo);
                }
                count += returnCount;
                boxCount += 1;
                detailDoc.append("billNo",billNo)
                        .append("materialNo",VtuzxUtil.getString(data,"materialNo"))
                        .append("materialName",VtuzxUtil.getString(data,"materialName"))
                        .append("materialSpec",VtuzxUtil.getString(data,"materialSpec"))
                        .append("unit",VtuzxUtil.getString(data,"unit"))
                        .append("batchNo",VtuzxUtil.getString(data,"batchNo"))
                        .append("supplier",VtuzxUtil.getString(data,"supplier"))
                        .append("supplierName",VtuzxUtil.getString(data,"supplierName"))
                        .append("stockNo",VtuzxUtil.getString(data,"stockNo"))
                        .append("barcodeType",barcodeType)
                        .append("boxNo",boxNo)
                        .append("createUserName",name)
                        .append("_createUserId",userId)
                        .append("returnCount",returnCount);//退的数量
                detailList.add(detailDoc);
            }

        }
        purReturnDetailDao.insertMany(detailList);
        Document purReturnDoc = new Document();//外层数据
        purReturnDoc.append("count",count)
                .append("boxCount",boxCount)
                .append("prdInBillNo",prdInBillNo)
                .append("supplierNo",supplierNo)
                .append("supplierName",supplierName)
                .append("createUserName",name)
                .append("_createUserId",userId)
                .append("billNo",billNo);
        ObjectId _id = purReturnDao.insertOne(purReturnDoc);
        //反写detail层数据
        purReturnDetailDao.updateManyRedirect(Criteria.where("billNo").is(billNo),new Document("$set",new Document("_purReturnId",_id)));

        //做出库
        try {
            inventoryService.reduceInventory(userId, name, BillEvent.Audit, BillType.CGTH, stockNo, billNo, boxNoList, bcBoxList, null);
            //传金蝶
            syncKingdeeOrderService.syncPurOrderReturn(userId,name,billNo,"pda");
        } catch (Exception e){
            throw e;
        }
    }

    @Override
    public VtuzxMap getPurReturnBill(ObjectId userId, int pageIndex, int pageSize, Map<String, Object> param) {

        String billNo = VtuzxUtil.getString(param, "billNo");
        String supplierName = VtuzxUtil.getString(param,"supplierName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(billNo)){
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(supplierName)){
            cond.and("supplierName").regex(supplierName);
        }
        if (!VtuzxUtil.isEmpty(createTime)){
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }

        List<VtuzxMap> dataList = new ArrayList<>();
        VtuzxPage page = purReturnDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime")))
                .append("supplierName",VtuzxUtil.getString(doc,"supplierName"))
                .append("boxCount", VtuzxUtil.getInt(doc, "boxCount"))
                .append("count", VtuzxUtil.getDouble(doc, "count")));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getPurReturnByBillNo(ObjectId userId, String billNo) {
        Document purInDoc = purReturnDao.findOne(Criteria.where("billNo").is(billNo));
        String createUserName = VtuzxUtil.getString(purInDoc, "createUserName");
        int boxCount = VtuzxUtil.getInt(purInDoc, "boxCount");
        double count = VtuzxUtil.getDouble(purInDoc, "count");
        String supplierName = VtuzxUtil.getString(purInDoc,"supplierName");
        String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(purInDoc, "createTime"));
        VtuzxMap header = new VtuzxMap("billNo", billNo)
                .append("createUserName", createUserName)
                .append("createTime", createTime)
                .append("boxCount", boxCount)
                .append("supplierName",supplierName)
                .append("count", count);

        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> purInDetailItr = purReturnDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (purInDetailItr.hasNext()) {
            Document purInDetailDoc = purInDetailItr.next();
            VtuzxMap purInDetailMap = new VtuzxMap(purInDetailDoc);
            purInDetailMap.remove("_createUserId");
            purInDetailMap.remove("createUserName");
            purInDetailMap.remove("_updateUserId");
            purInDetailMap.remove("updateUserName");
            dataList.add(purInDetailMap);
        }
        return new VtuzxMap("header", header).append(IVtuzxConst.Key_data, dataList);
    }

    /**
     * 导出采购入库单
     * @param token
     * @param param
     * @return
     * @throws Exception
     */
    @Override
    public VtuzxDownloadBean downloadPurInList(VtuzxToken token, Map<String, Object> param) throws Exception {
        String stockNo = VtuzxUtil.getString(param, "stockNo");
        String type = VtuzxUtil.getString(param, "type");
        String billNo = VtuzxUtil.getString(param, "billNo");

        String createUserName = VtuzxUtil.getString(param, "createUserName");
        List<String> createTime = VtuzxUtil.getObject(param, "createTime");
        Criteria cond = new Criteria();
        cond.and("count").ne(0);
        List<Document> dataList = new ArrayList<>();
        if (!VtuzxUtil.isEmpty(stockNo)) {
            cond.and("stockNo").is(stockNo);
        }
        if (!VtuzxUtil.isEmpty(type)) {
            cond.and("isBc").is(true);
        } else {
            cond.and("isBc").ne(true);
        }
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            String[] splitList = createUserName.split("，");
            if (splitList.length == 1) {
                cond.and("createUserName").regex(createUserName);
            } else {
                List<String> split = new ArrayList<>(Arrays.asList(splitList));//数组转list
                cond.and("createUserName").in(split);
            }
        }
        if (!VtuzxUtil.isEmpty(createTime)) {
            cond.and("createTime").gte(VtuzxUtil.parseDate(createTime.get(0))).lte(VtuzxUtil.parseDate(createTime.get(1) + " 23:59:59"));
        }
        List<String> billNoList = new ArrayList<>();
        Map<String,Object> statusMap = new HashMap<>();//key;单据编号  value:状态
        Iterator<Document> purInItr = purInDao.findList(cond,new Document("createTime",-1),0,0);
        while (purInItr.hasNext()){
            Document purInDoc = purInItr.next();
            String purInBillNo = VtuzxUtil.getString(purInDoc,"billNo");
            String status = VtuzxUtil.getString(purInDoc,"status");
            if (!billNoList.contains(purInBillNo)){
                billNoList.add(purInBillNo);
            }
            if ("audit".equals(status)){
                statusMap.put(purInBillNo,"审核");
            } else {
                statusMap.put(purInBillNo,"保存");
            }
        }
        List<String> stockNoList = new ArrayList<>();//仓库集合
        Iterator<Document> purInDetailItr = purInDetailDao.findList(Criteria.where("billNo").in(billNoList),new Document("createTime",-1),0,0);
        while (purInDetailItr.hasNext()){
            Document purInDetailDoc = purInDetailItr.next();
            String detailStockNo = VtuzxUtil.getString(purInDetailDoc,"stockNo");
            dataList.add(purInDetailDoc);
            if (!stockNoList.contains(detailStockNo)){
                stockNoList.add(detailStockNo);
            }
        }
        //查询仓库名称
        VtuzxMap stockMap = new VtuzxMap();
        Iterator<Document> stockItr = stockDao.findList(Criteria.where("fNumber").in(stockNoList), null, 0, 0);
        while (stockItr.hasNext()) {
            Document stock = stockItr.next();
            String stockNumber = VtuzxUtil.getString(stock, "fNumber");
            String stockName = VtuzxUtil.getString(stock, "fName");
            stockMap.append(stockNumber, stockName);
        }
        for (Document otherDoc : dataList){
            String otherStockNo = VtuzxUtil.getString(otherDoc,"stockNo");
            String otherBillNo = VtuzxUtil.getString(otherDoc,"billNo");
            String stockName = VtuzxUtil.getString(stockMap,otherStockNo);//仓库名称
            String status = VtuzxUtil.getString(statusMap,otherBillNo);//状态
            otherDoc.append("stockName",stockName);
            otherDoc.append("status",status);
        }
        VtuzxDownloadBean vtuzxDownloadBean = produceService.downloadBean(dataList, "采购入库");
        return vtuzxDownloadBean;
    }





    private void uploadBoxNo(File file)throws Exception{
        List<VtuzxExcelSheet> sheets = VtuzxExcel.read(file);
        VtuzxExcelSheet sheet = sheets.get(0);
        int rowSize = sheet.rowSize();
        List<String> boxNoList = new ArrayList<>();
        for (int i = 0; i < rowSize; i++){
            String boxNo = sheet.row(i).cell(0).strCellValue();
            if (!boxNoList.contains(boxNo)){
                boxNoList.add(boxNo);
            }
        }
        System.out.println("");
        //获取令牌
        Document storeDoc = storeTokenDao.findOne(Criteria.where("type").is("kingdee"));
        //即时库存查询箱号对应的货品以及数量
        Iterator<Document> detailItr = inventoryDetailDao.findList(Criteria.where("boxNo").in(boxNoList),null,0,0);
        List<Document> boxList = new ArrayList<>();
        while (detailItr.hasNext()){
            Document detailDoc = detailItr.next();

            boxList.add(detailDoc);
        }

        BillType billType = BillType.SCRK;
        for (Document doc : boxList){
            String boxNo = VtuzxUtil.getString(doc,"boxNo");
            String inventoryId = VtuzxUtil.getString(doc, "_inventoryId");
            //从外层表中取出物料信息
            Document invenDoc = inventoryDao.findById(inventoryId);
            String materialNo = VtuzxUtil.getString(invenDoc, "materialNo");
            List<Document> traceBack = VtuzxUtil.getObject(doc, "traceBack");
            Document prdColDoc = prdColDetailDao.findOne(Criteria.where("boxNo").is(boxNo));

            double count = VtuzxUtil.getDouble(prdColDoc,"count");
            String id = VtuzxUtil.getString(prdColDoc,"_id");
            List<VtuzxMap> boxSerialList = new ArrayList<>();//箱子接口唯一码参数
            List<String> traceBackList = new ArrayList<>();//存储整理后的追溯码
            for (Document trace : traceBack) {
                String traceNo = VtuzxUtil.getString(trace, "traceBackNo");
                traceBackList.add(traceNo);
                VtuzxMap traceMap = new VtuzxMap("sn", traceNo);
                boxSerialList.add(traceMap);

            }


            VtuzxMap goodsMap = new VtuzxMap();//getGoodsList方法返回值
            //需要先获取条码(skubarcode)
            VtuzxMap goodsParam = new VtuzxMap();
            goodsParam.append("pageIndex", 0)
                    .append("pageSize", 1)
                    .append("goodsNo", materialNo);
            try {
                goodsMap = iJiKeYunApiService.getGoodsList(storeDoc, goodsParam);
            } catch (Exception e) {
                throw new VtuzxException(e.getMessage());
            }

            LinkedHashMap result = VtuzxUtil.getObject(goodsMap, "result");
            LinkedHashMap data = VtuzxUtil.getObject((Map<String, Object>) result, "data");
            List<LinkedHashMap> goods = VtuzxUtil.getObject((Map<String, Object>) data, "goods");
            LinkedHashMap goodsResult = goods.get(0);
            String skuId = VtuzxUtil.getString((Map<String, Object>) goodsResult, "skuId");
            //传入唯一码
            //查询规格
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            String materialName = VtuzxUtil.getString(materialDoc, "fName");
            //创建箱子
            VtuzxMap boxParam = new VtuzxMap();//箱码总参数
            List<VtuzxMap> boxDetailList = new ArrayList<>();//入库申请单明细

            int serialCount = boxSerialList.size();//每个箱子的唯一码数量
            boxDetailList.add(new VtuzxMap("goodsNo", materialNo)
                    .append("goodsName", materialName)
                    .append("skuId", skuId)
                    .append("boxCount", serialCount)
                    .append("snList", boxSerialList));
            boxParam.append("boxCount", 1)
                    .append("boxDetailList", boxDetailList)
                    .append("isAuto", 3)
                    .append("boxNo", billType.barcodeKey() + "|;" + id + "|;" + materialNo + "|;" + "888888" + "|;" + count +"|;" +boxNo);


            try {
                iJiKeYunApiService.createBoxBatch(storeDoc, boxParam);
            } catch (Exception e) {
                throw new VtuzxException(e.getMessage());
            }

        }
    }
}
